package com.firemoss.magicbus.rpc
{
	import com.firemoss.magicbus.event.DefaultMessagingEventMediator;
	import com.firemoss.magicbus.event.IMessagingEventMediator;
	
	import flash.utils.flash_proxy;
	
	import mx.core.mx_internal;
	import mx.rpc.AbstractOperation;
	import mx.rpc.remoting.mxml.RemoteObject;

	use namespace mx_internal;
	use namespace flash_proxy;

	[DefaultProperty("methods")]
	
	public dynamic class Service extends RemoteObject
	{
		
		include "./filterProperties.inc";
		include "./mediationProperties.inc";

		public var eventMediator : IMessagingEventMediator

		public function get mxmlId() : String
		{
			return this.id
		}
    
   		public function set methods( value : Object ) : void
		{
			if ( !( value is Array ) )
			{
				value = [ value ]
			}
			
			_methods = {}

			for each ( var method : AbstractOperation in ( value as Array ) ) 
			{
				if ( method.name != null )
				{
					_methods[ method.name ] = method
				}
			}
		}
		public function get methods() : Object
		{
			return _methods
		}
		private var _methods : Object
		
		public function Service(destination:String=null)
		{
			super(destination);
			
			convertResultHandler = executeResponseChain
			
			eventMediator = new DefaultMessagingEventMediator( this )
		}

	    override public function getOperation(name:String):AbstractOperation
	    {
	        var o:Object = _operations[name];
	        var op:AbstractOperation = (o is AbstractOperation) ? AbstractOperation(o) : null;
	        
	        if ( op == null )
	        {
	        	op = _methods[ name ] != null ? _methods[ name ] as AbstractOperation : null
	        	
	        	if ( op )
	        	{
		            _operations[name] = op;
		            op.asyncRequest = asyncRequest;
		            
		            if ( op is ServiceMethod )
		            {
			            ServiceMethod( op ).rpcService = this
			            op.setService( this )
		            }
		        }
	        }
	        
	        if (op == null)
	        {
	            op = new ServiceMethod(this, name);
	            _operations[name] = op;
	            op.asyncRequest = asyncRequest;
	        }
	        return op;
	    }
	    
		public function dispatchRpcEvent( eventName : String, body : *, bodyPropertyName : String = null, additionalProperties : Object = null, eventClass : Class = null ) : void
		{
			if ( eventMediator )
			{
				eventMediator.createAndDispatch( eventName, body, bodyPropertyName, additionalProperties, eventClass )
			}
		}
	    
	    private function executeResponseChain( result : *, operation : AbstractOperation ) : *
	    {
	    	if ( operation is ServiceMethod && ServiceMethod( operation ).responseChain )
	    	{
	    		result = ServiceMethod( operation ).responseChain.execute( result )[ 0 ]
	    	} 
	    	
	    	if ( responseChain )
	    	{
	    		result = responseChain.execute( result )[ 0 ]
	    	}
	    	
	    	return result
	    }
    		
	}
}